home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 16 / IOPROG_16.ISO / soft / macaxsdk / macsdk.hqx / ActiveX DR3 SDK / ActiveX SDK / Container Common / pullstream.cpp / pullstream.cpp
Encoding:
Text File  |  1997-08-04  |  9.3 KB  |  380 lines  |  [TEXT/CWIE]

  1. //
  2. //  PullStream.CPP
  3. //
  4. // >>> ⌐ 1996-1997 Microsoft Corporation.  All rights reserved. <<<
  5. //
  6. //  Implements pull-data type stream access
  7. //
  8.  
  9. #include "AXContainerHeaders.h"
  10.  
  11. extern FORMATETC g_NullFormatEtc;
  12.  
  13.  
  14. //
  15. //  CPullStreamNotify::~CPullStreamNotify
  16. //
  17.  
  18. CPullStreamNotify::~CPullStreamNotify()
  19. {
  20.     if (m_pStream != NULL)
  21.         CoTaskMemFree(m_pStream);
  22. }
  23.  
  24. //
  25. //  CPullStreamNotify::OnWrite
  26. //
  27.  
  28. int32
  29. CPullStreamNotify::OnWrite(NPStream *stream, int32 offset, int32 len, void
  30.     *buffer)
  31. {
  32. #pragma unused (stream, offset)
  33.     int32 BytesWritten;
  34.  
  35.     if (m_pStream == NULL)
  36.         m_pStream = (LPVOID) CoTaskMemAlloc(STREAM_BUFFER_SIZE);
  37.  
  38.     if ((m_StreamLength + len) <= STREAM_BUFFER_SIZE)
  39.     {
  40.         BlockMove(buffer, ((LPBYTE) m_pStream + m_StreamLength), len);
  41.         m_StreamLength += len;
  42.         BytesWritten = len;
  43.     }
  44.     else
  45.     {
  46.         //  Returning a negative value causes the stream to error out and be
  47.         //  destroyed.
  48.         BytesWritten = -1;
  49.     }
  50.     
  51.     m_ReadyToRead -= len;
  52.  
  53.     return BytesWritten;
  54. }
  55.  
  56. int32
  57. CPullStreamNotify::OnWriteReady(NPStream *stream)
  58. {
  59. #pragma unused (stream)
  60.     return m_ReadyToRead;
  61. }
  62.  
  63. //
  64. //  CPullOleStreamNotify::IUnknown::QueryInterface
  65. //
  66.  
  67. STDMETHODIMP
  68. CPullOleStreamNotify::QueryInterface(REFIID riid, LPVOID *ppvObj)
  69. {
  70.     HRESULT hr;
  71.     LPVOID pv;
  72.  
  73.     if (riid == IID_IUnknown || riid == IID_IStream) {
  74.         pv = (LPVOID)(LPSTREAM) this;
  75.         ++m_cRef;
  76.         hr = ResultFromScode(S_OK);
  77.     } else {
  78.         pv = NULL;
  79.         hr = ResultFromScode(E_NOINTERFACE);
  80.     }
  81.  
  82.     *ppvObj = pv;
  83.     return hr;
  84. }
  85.  
  86. //
  87. //  CPullOleStreamNotify::IUnknown::AddRef
  88. //
  89.  
  90. STDMETHODIMP_(ULONG)
  91. CPullOleStreamNotify::AddRef(void)
  92. {
  93.     return ++m_cRef;
  94. }
  95.  
  96. //
  97. //  CPullOleStreamNotify::IUnknown::Release
  98. //
  99.  
  100. STDMETHODIMP_(ULONG)
  101. CPullOleStreamNotify::Release(void)
  102. {
  103.     if (--m_cRef != 0)
  104.         return m_cRef;
  105.  
  106.     delete this;
  107.     return 0;
  108. }
  109.  
  110. //
  111. //  CPullOleStreamNotify::IStream::Read
  112. //
  113.  
  114. STDMETHODIMP
  115. CPullOleStreamNotify::Read(void *pv, DWORD cb, LPDWORD pcbRead)
  116. {
  117.     //  Verify that we're not try to read more bytes than are available.  If we
  118.     //  are, clip the actual number of bytes copied.  The OLE32 memory stream
  119.     //  implementation doesn't return an error, so we won't either.
  120.     if (((LONG) cb < 0) || (cb + (ULONG) m_SeekPosition > (ULONG) m_StreamLength))
  121.     {
  122.         if (m_fAsyncStreamInProgress)
  123.         {
  124.             //  Special case: if we're in the middle of streaming some data from
  125.             //  the network, return E_PENDING so that async binding works
  126.             //  correctly.
  127.             //  BUGBUG:  Above if statement probably isn't adequate, review this.
  128.             return ResultFromScode(E_PENDING);
  129.         } 
  130.         else
  131.         {
  132.             cb = m_StreamLength - m_SeekPosition;
  133.         }
  134.     }
  135.  
  136.     if (cb > 0)
  137.     {
  138.         BlockMove((LPBYTE) m_pStream + m_SeekPosition, pv, cb);
  139.         m_SeekPosition += cb;
  140.     }
  141.  
  142.     if (pcbRead != NULL)
  143.         *pcbRead = cb;
  144.  
  145.     // if all data has been read, pull another buffer full
  146.     if(m_ReadyToRead == 0 && m_SeekPosition >= STREAM_BUFFER_SIZE)
  147.     {
  148.         m_SeekPosition = 0;
  149.         m_StreamLength = 0;
  150.         m_ReadyToRead = STREAM_BUFFER_SIZE;
  151.     }
  152.  
  153.     return ResultFromScode(S_OK);
  154. }
  155.  
  156. //
  157. //  CPullOleStreamNotify::IStream::Write
  158. //
  159.  
  160. STDMETHODIMP
  161. CPullOleStreamNotify::Write(void const *pv, DWORD cb, LPDWORD pcbWritten)
  162. {
  163. #pragma unused (pv, cb, pcbWritten)
  164.     return ResultFromScode(STG_E_ACCESSDENIED);
  165. }
  166.  
  167. //
  168. //  CPullOleStreamNotify::IStream::Seek
  169. //
  170.  
  171. STDMETHODIMP
  172. CPullOleStreamNotify::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
  173.     ULARGE_INTEGER *plibNewPosition)
  174. {
  175. #pragma unused (dlibMove, dwOrigin, plibNewPosition)
  176.     return ResultFromScode(STG_E_INVALIDFUNCTION);
  177. }
  178.  
  179. //
  180. //  CPullOleStreamNotify::IStream::SetSize
  181. //
  182.  
  183. STDMETHODIMP
  184. CPullOleStreamNotify::SetSize(ULARGE_INTEGER libNewSize)
  185. {
  186. #pragma unused (libNewSize)
  187.     //  We're a read-only stream, so there's no reason to resize our stream.
  188.     return ResultFromScode(STG_E_INVALIDFUNCTION);
  189. }
  190.  
  191. //
  192. //  CPullOleStreamNotify::IStream::CopyTo
  193. //
  194.  
  195. STDMETHODIMP
  196. CPullOleStreamNotify::CopyTo(LPSTREAM pstm, ULARGE_INTEGER cb, ULARGE_INTEGER
  197.     *pcbRead, ULARGE_INTEGER *pcbWritten)
  198. {
  199. #pragma unused (pstm, cb, pcbRead, pcbWritten)
  200.     //  There's no good reason for this not to be implemented.
  201.     return ResultFromScode(E_NOTIMPL);
  202. }
  203.  
  204. //
  205. //  CPullOleStreamNotify::IStream::Commit
  206. //
  207.  
  208. STDMETHODIMP
  209. CPullOleStreamNotify::Commit(DWORD grfCommitFlags)
  210. {
  211. #pragma unused (grfCommitFlags)
  212.     //  We can always "commit" because it's not possible to write to the stream.
  213.     return ResultFromScode(S_OK);
  214. }
  215.  
  216. //
  217. //  CPullOleStreamNotify::IStream::Revert
  218. //
  219.  
  220. STDMETHODIMP
  221. CPullOleStreamNotify::Revert(void)
  222. {
  223.     //  We can always "revert" because it's not possible to write to the stream.
  224.     return ResultFromScode(S_OK);
  225. }
  226.  
  227. //
  228. //  CPullOleStreamNotify::IStream::LockRegion
  229. //
  230.  
  231. STDMETHODIMP
  232. CPullOleStreamNotify::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
  233.     DWORD dwLockType)
  234. {
  235. #pragma unused (libOffset, cb, dwLockType)
  236.     return ResultFromScode(STG_E_INVALIDFUNCTION);
  237. }
  238.  
  239. //
  240. //  CPullOleStreamNotify::IStream::UnlockRegion
  241. //
  242.  
  243. STDMETHODIMP
  244. CPullOleStreamNotify::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER
  245.     cb, DWORD dwLockType)
  246. {
  247. #pragma unused (libOffset, cb, dwLockType)
  248.     return ResultFromScode(STG_E_INVALIDFUNCTION);
  249. }
  250.  
  251. //
  252. //  CPullOleStreamNotify::IStream::Stat
  253. //
  254.  
  255. STDMETHODIMP
  256. CPullOleStreamNotify::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  257. {
  258. #pragma unused (grfStatFlag)
  259.     //  Implementation lifted from OLE32's memory stream.
  260.     memset(pstatstg, 0, sizeof(*pstatstg));
  261.     pstatstg->type = STGTY_STREAM;
  262.     pstatstg->cbSize.LowPart = m_StreamLength;
  263.     return ResultFromScode(S_OK);
  264. }
  265.  
  266. //
  267. //  CPullOleStreamNotify::IStream::Clone
  268. //
  269.  
  270. STDMETHODIMP
  271. CPullOleStreamNotify::Clone(LPSTREAM *ppstm)
  272. {
  273.     *ppstm = NULL;
  274.     return ResultFromScode(E_NOTIMPL);
  275. }
  276.  
  277. //
  278. //  CBindingMemoryStreamNotify::OnWrite
  279. //
  280. //  Extends the default memory stream implementation by notifying the client of
  281. //  data availability.
  282. //
  283.  
  284. int32
  285. CBindingPullStreamNotify::OnWrite(NPStream *stream, int32 offset, int32 len,
  286.     void *buffer)
  287. {
  288.     int32 BytesWritten;
  289.     ULONG BindStatus;
  290.     DWORD fBSCF;
  291.  
  292.     //  Tag the stream such that requests for unavailable data made against our
  293.     //  IStream return E_PENDING.
  294.     m_fAsyncStreamInProgress = TRUE;
  295.  
  296.     BytesWritten = CPullOleStreamNotify::OnWrite(stream, offset, len, buffer);
  297.  
  298.     if (BytesWritten > 0) {
  299.  
  300.         if (!m_fDeliveredFirstNotify) {
  301.             m_fDeliveredFirstNotify = TRUE;
  302.             BindStatus = BINDSTATUS_BEGINDOWNLOADDATA;
  303.             fBSCF = BSCF_FIRSTDATANOTIFICATION;
  304.         } else {
  305.             BindStatus = BINDSTATUS_DOWNLOADINGDATA;
  306.             fBSCF = BSCF_INTERMEDIATEDATANOTIFICATION;
  307.         }
  308.  
  309.         m_pBinding->m_pbsc->OnProgress((ULONG) m_StreamLength, 
  310.             (ULONG) m_StreamLength, BindStatus, m_pszURL);
  311.  
  312.         mStorageMedium.tymed = TYMED_ISTREAM;
  313.         mStorageMedium.u.pstm = (LPSTREAM) this;
  314.         mStorageMedium.pUnkForRelease = (LPUNKNOWN) this;
  315.         m_pBinding->m_pbsc->OnDataAvailable(fBSCF, BytesWritten,
  316.             &g_NullFormatEtc, &mStorageMedium);
  317.  
  318.         //  If the client called IBinding::Abort, return an error so as to
  319.         //  force the stream to terminate.
  320.         if (m_pBinding->m_fAborted)
  321.             BytesWritten = -1;
  322.     }
  323.  
  324.     //  If BytesWritten is negative, then the stream will be terminated.  The
  325.     //  client will be notified of the error in the OnDestroyStream method.
  326.     return BytesWritten;
  327. }
  328.  
  329. //
  330. //  CBindingMemoryStreamNotify::OnDestroyStream
  331. //
  332. //  Extends the default memory stream implementation by notifying the client
  333. //  that the binding operation is complete.
  334. //
  335.  
  336. NPError
  337. CBindingPullStreamNotify::OnDestroyStream(NPStream *stream, NPError reason)
  338. {
  339. #pragma unused (stream)
  340.     HRESULT hr;
  341.  
  342.     m_fAsyncStreamInProgress = FALSE;
  343.  
  344.     //  You would think Netscape would pass the right reason code to us, but it
  345.     //  always returns a zero on success, so maybe they want NPERR_NO_ERROR???
  346.     if ((reason == NPERR_NO_ERROR || reason == NPRES_DONE) &&
  347.         !m_pBinding->m_fAborted) {
  348.         //  Send the final progress notification.
  349.         m_pBinding->m_pbsc->OnProgress((ULONG) m_StreamLength,
  350.             (ULONG) m_StreamLength, BINDSTATUS_ENDDOWNLOADDATA, m_pszURL);
  351.  
  352.         //  Although the data stream hasn't changed, we need to send the last
  353.         //  data notification.
  354.         mStorageMedium.tymed = TYMED_ISTREAM;
  355.         mStorageMedium.u.pstm = (LPSTREAM) this;
  356.         mStorageMedium.pUnkForRelease = (LPUNKNOWN) this;
  357.         m_pBinding->m_pbsc->OnDataAvailable(BSCF_LASTDATANOTIFICATION,
  358.             m_StreamLength, &g_NullFormatEtc, &mStorageMedium);
  359.  
  360.         hr = ResultFromScode(S_OK);
  361.     } else {
  362.         hr = ResultFromScode(E_ABORT);
  363.     }
  364.  
  365.     //  Notify the callback that the binding has stopped.  Plus, we're through
  366.     //  with the binding object, so we're ready to throw it away.  The client
  367.     //  is supposed to release the pointer in the OnStopBinding method, so we'll
  368.     //  make sure we don't leak anything by just deleting the binding.
  369.     m_pBinding->m_pbsc->OnStopBinding(hr, NULL);
  370.     delete m_pBinding;
  371.     m_pBinding = NULL;
  372.  
  373.     //  We're through with this binding callback object.  The user may be
  374.     //  holding on to our stream object though, so we must pay attention to our
  375.     //  reference count.
  376.     this->Release();
  377.  
  378.     return NPERR_NO_ERROR;
  379. }
  380.